using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using MathSharp;
using MathSharp.Utils;
using System.Text.RegularExpressions;

namespace MathSharp.Script
{
	public class VarBlock: BaseCommand
	{
		string varibleName;
		ValueType variableType;
		Variable varible;
		
		public VarBlock (Script script): base(script)
		{
		}
	

		public override Value Execute ()
		{
			return base.Execute ();
		}

		public override string Name {
			get {
				if (varibleName.IsNullOrWhiteSpace())
					return "varible";
				else
					return "varible {0}".format(varibleName);
			}
		}

		public override void Parse (IList<string> scriptText)
		{
			if (scriptText.Count <= 0)
				throw new ParseException(script.FileName, scriptText.GetOriginalLineSmarts(0), 0, 0x0,
				                         "Некоректый формат объявления переменной: блок объявления 0 строк");
			if (scriptText.Count > 1)
				throw new ParseException(script.FileName, scriptText.GetOriginalLineSmarts(0), 0, 0x0,
				                         "Некоректый формат объявления переменной: блок объявления болльще 1 строки");
			
			base.Parse (scriptText);
			ParsableStringReader sr = new ParsableStringReader(scriptText[0]);
			string commmand = sr.ReadToWhitespace();
			sr.SkipWhitespaceChars();
			string varType = null;
			string tmp = sr.ReadToWhitespace();
			if (tmp.IsNullOrWhiteSpace())
				throw new ParseException(script.FileName, scriptText.GetOriginalLineSmarts(0), sr.Offset, 0x0,
				                         "Ожидалось объявление переменной");
			if (tmp[0] != '$') { // объявление типа переменной
				varType = tmp;
				sr.ReadToWhitespace();
				tmp = sr.ReadToWhitespace();
				if (tmp.IsNullOrWhiteSpace())
					throw new ParseException(script.FileName, scriptText.GetOriginalLineSmarts(0), sr.Offset, 0x0,
					                         "Ожидалось объявление переменной");
			}
			// обявление имени переменной
			if (tmp[0] != '$')
				throw new ParseException(script.FileName, scriptText.GetOriginalLineSmarts(0), sr.Offset, 0x0,
				                         "Обявление имени переменной дожно начинатся со знака $, а указанно {0}", tmp);
			varibleName = tmp.Substring(1);
			if (varibleName.IsNullOrWhiteSpace())
				throw new ParseException(script.FileName, scriptText.GetOriginalLineSmarts(0), sr.Offset, 0x0,
				                         "Обявление переменной дожно содержать имя");
			Regex regex = new Regex(@"^[a-zA-Z_][a-zA-Z0-9_]*$");
			if (!regex.IsMatch(varibleName))
				throw new ParseException(script.FileName, scriptText.GetOriginalLineSmarts(0), sr.Offset, 0x0,
				                         "Обявление переменной содержит недопустимые символы в имени. Допускается использовать латинские символы, цифры и знак подчёркивания. Первй символ имени не может быть цифрой");
			
			variableType = (varType.IsNullOrWhiteSpace())?ValueType.Variable:Variable.ParseValueType(script, scriptText.GetOriginalLineSmarts(0), varType);
			
			// читаем дополнительные параметры переменной
			while (!sr.EOF) {
				sr.SkipWhitespaceChars();
				tmp = sr.ReadToWhitespace();
				switch (tmp.ToLower()) {
					case "external":
						sr.SkipWhitespaceChars();
						string externalName = sr.ReadStringDeclaration();
						break;
					case "=": // обявление значения
						throw new NotImplementedException("Обявление переменных с назначением значения в данный момент не реализованно");
						break;
					default:
						throw new ParseException(script.FileName, scriptText.GetOriginalLineSmarts(0), sr.Offset, 0x0,
						                         "Неизвестный параметр при объявлении переменной: {0}", tmp);
				}
			}
		}

		public override void PrepareExecute ()
		{
			base.PrepareExecute ();
		}
	}
}

